package fire.and.near.challenger.facebook;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;

import com.facebook.FacebookException;
import com.facebook.Request;
import com.facebook.Request.GraphUserListCallback;
import com.facebook.Response;
import com.facebook.Session;
import com.facebook.SessionState;
import com.facebook.model.GraphUser;

/**
 * 
 * @author NeaR
 * 
 */
public class FacebookHelper {

	private static final String PERMISSIONS = "publish_actions";
	private static final String PLACE = "473076199491036";
	private Session mSession = null;
	private GraphUser mMe;

	/**
	 * Called from onActivityResult method in the activity used to issue the
	 * request
	 */
	public void onActivityResult(Activity currentActivity, int requestCode,
			int resultCode, Intent data) {

		Session.getActiveSession().onActivityResult(currentActivity,
				requestCode, resultCode, data);
	}

	/**
	 * Used to request publish permission, so the application can post on
	 * Facebook on behalf of the user
	 * 
	 * @param activity
	 *            The activity used to issue the request
	 * @return <b>true</b> if successful, <b>false</b> if failed
	 */
	public boolean getPublishPermission(Activity activity) {
		if (mSession != null) {
			try {
				mSession.requestNewPublishPermissions(new Session.NewPermissionsRequest(
						activity, PERMISSIONS));
				return true;
			} catch (FacebookException ex) {
				return false;
			}
		} else {
			return false;
		}
	}

	/**
	 * Checks if the application has <i>publish_actions</i>
	 * and <i>publish_stream</i> permissions
	 * 
	 * @return <b>true</b> if it has, <b>false</b> if it doesn't
	 */
	public boolean hasPublishPermission() {
		mSession = Session.getActiveSession();
		return mSession != null
				&& mSession.getPermissions().contains("publish_actions");
	}

	/**
	 * Checks if the session is active. If it <i>IS NOT</i>, a new login request
	 * is needed
	 * 
	 * @return <b>true</b> if the current session is active, <b>false</b> if
	 *         it's not
	 */
	public boolean isSessionActive() {
		return Session.getActiveSession() != null;
	}
	
	/**
	 * Gets the current user's Facebook ID
	 * @return user's Facebook ID or 0 if the current user is null
	 */
	public long getMyFacebookId() {
		return mMe != null ? Long.parseLong(mMe.getId()) : 0;
	}

	/**
	 * Called to login the user. If used for the first time, will open
	 * webview/activity and ask for facebook username and password. Returns
	 * facebook access token which is automatically handled by the OS. If there
	 * is already an active access token, the user won't notice the login
	 * process.
	 * 
	 * @param activity
	 *            The activity used to issue the request
	 * @param action
	 *            The action handler used when the login is completed
	 * @throws FacebookException
	 *             If there is an error while trying to login the user
	 */
	public void login(final Activity activity, final IFacebookAction action)
			throws FacebookException {

		Session.openActiveSession(activity, true, new Session.StatusCallback() {

			@Override
			public void call(Session session, SessionState state,
					Exception exception) {
				if (session.isOpened() && state.isOpened()) {

					Request.newMeRequest(session,
							new Request.GraphUserCallback() {

								@Override
								public void onCompleted(final GraphUser user,
										final Response response) {

									mSession = Session.getActiveSession();
									mMe = user;
									
									if (!hasPublishPermission()) {
										getPublishPermission(activity);
									} else {
										action.onLoginCompleted(user, response);
									}
								}
							}).executeAsync();
				}
			}
		});
	}
	
	/**
	 * Logout the user, clearing the stored access token
	 */
	public void logout() {
		if(mSession != null) {
			Log.i("FacebookHelper", "LOGOUT SUCCESS");
			mSession.closeAndClearTokenInformation();
		} else {
			Log.i("FacebookHelper", "LOGOUT FAIL");
		}
	}

	
	public void postStatusUpdate(	Activity context, 
									final String message, 
									final String tags, 
									Bitmap bitmap, 
									final IFacebookAction action) 
											throws FacebookException {
		
		if (hasPublishPermission()) {
			if (bitmap == null) {
				Request request = Request.newStatusUpdateRequest(mSession, message,
						new Request.Callback() {
							@Override
							public void onCompleted(Response response) {
								action.onActionCompleted(response);
							}
						});

				if(tags != null) {
					Bundle params = request.getParameters();
					params.putString("place", PLACE);
					params.putString("tags", tags);
					request.setParameters(params);
				}
				
				request.executeAsync();
			} else {
				Request request = Request.newUploadPhotoRequest(mSession, bitmap,
						new Request.Callback() {
							@Override
							public void onCompleted(Response response) {
								
								if(response.getError() == null) {
									String idUploadResponse= (String) response.getGraphObject().getProperty("id");
									
						            if (idUploadResponse!= null) {
						                String fbPhotoAddress = 
						                		"https://www.facebook.com/photo.php?fbid=" 
						                		+ idUploadResponse;
						                
						                Request request2 = Request.newStatusUpdateRequest(mSession, message,
						    					new Request.Callback() {
						    						@Override
						    						public void onCompleted(Response response) {
						    							action.onActionCompleted(response);
						    						}
						    					});
						                
						                Bundle params = request2.getParameters();
						                
						                if(tags != null) {
						    				params.putString("place", PLACE);
						    				params.putString("tags", tags);	
						    			}
						                
						                params.putString("link", fbPhotoAddress);
					    				request2.setParameters(params);
						    			
						    			request2.executeAsync();
						            }
								} else {
									Log.i("IN UPLOAD COMPL", response.getError().getErrorMessage()); ////////////////
								}
							}
						}
				);
				
				Bundle params = request.getParameters();
				params.putString("message", message);
				request.setParameters(params);
				
				request.executeAsync();
			}
		} else {
			getPublishPermission(context);
			throw new FacebookException();
		}
	}

	/**
	 * Creates 'Challenger' album and uploads a photo in it, adding an
	 * additional message
	 * 
	 * @param activity
	 *            The activity used to issue the request
	 * @param bitmap
	 *            The bitmap image to be uploaded
	 * @param message
	 *            The message to be added to the uploaded image
	 * @param action
	 *            The action handler used when the upload is completed
	 * @throws FacebookException
	 */
	public void uploadPhoto(Activity activity, Bitmap bitmap, String message, final String tags,
			final IFacebookAction action) throws FacebookException {

		if (hasPublishPermission()) {
			Request request = Request.newUploadPhotoRequest(mSession, bitmap,
					new Request.Callback() {
						@Override
						public void onCompleted(Response response) {
							action.onActionCompleted(response);
						}
					});

			Bundle params = request.getParameters();
			params.putString("message", message);
			request.setParameters(params);
			request.executeAsync();

		} else {
			getPublishPermission(activity);
			throw new FacebookException();
		}
	}

	/**
	 * Gets the sorted friends list of the user
	 * @param activity
	 * @param action
	 * @throws FacebookException
	 */
	public void getFriends(Activity activity, final IFacebookAction action)
			throws FacebookException {

		if (mSession.getState().isOpened()) {
			Request friendRequest = Request.newMyFriendsRequest(mSession,
					new GraphUserListCallback() {
						@Override
						public void onCompleted(List<GraphUser> users,
								Response response) {

							Collections.sort(users,
									new Comparator<GraphUser>() {

										@Override
										public int compare(GraphUser lhs,
												GraphUser rhs) {
											return lhs.getName()
													.compareToIgnoreCase(
															rhs.getName());
										}

									});

							Log.i("INFO", response.toString());
							action.onGetFriends(users, response);
						}
					});

			Bundle params = new Bundle();
			params.putString("fields", "id, name, picture");
			friendRequest.setParameters(params);
			friendRequest.executeAsync();
		} else {
			throw new FacebookException();
		}
	}
}
